home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / xv / xvscreen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  39.2 KB  |  1,232 lines

  1. /* XView panel stuff.
  2.    Copyright (C) 1995 Jakub Jelinek.
  3.    
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2 of the License, or
  7.    (at your option) any later version.
  8.    
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. #include <config.h>
  19. #include <X11/Xatom.h>
  20. #include <xview/xview.h>
  21. #include <xview/frame.h>
  22. #include <xview/panel.h>
  23. #include <xview/canvas.h>
  24. #include <xview/scrollbar.h>
  25. #include <xview/svrimage.h>
  26. #include <xview/win_event.h>
  27. #include <xview/cms.h>
  28. #include <xview/dragdrop.h>
  29. #include <xview/cursor.h> 
  30. #include <xview/rect.h>
  31. #include <string.h>
  32.  
  33. #include "mad.h"
  34. #include "mem.h"
  35. #include "fs.h"
  36. #include "dir.h"
  37. #include "panel.h"
  38. #include "dlg.h"
  39. #include "widget.h"
  40. #include "command.h"
  41. #include "cmd.h"
  42. #include "main.h"
  43. #include "xvmain.h"
  44. #include "xvscreen.h"
  45. #include "util.h"
  46.  
  47. void do_enter (WPanel *panel);
  48.  
  49. extern Server_image iconRegular [2];
  50. extern Server_image iconDirectory [2];
  51.  
  52. extern WPanel *current_panel;
  53. extern WCommand *cmdline;
  54. extern Cursor dropcursor;
  55. extern Dlg_head *midnight_dlg;
  56. extern Cms mccms;
  57. extern Display *dpy;
  58.  
  59. extern int is_right;
  60.  
  61. #define PANELITEMBORDER 2
  62. #define PANELBORDER    4
  63.  
  64. static void xv_panel_repaint_proc (Canvas canvas, Xv_Window paint_window,
  65.     Rectlist *repaint);
  66.     
  67. void show_dir (WPanel *panel)
  68. {
  69.     /* This routine should update the current directory label */
  70.     xv_set ((Frame) xv_get ((Canvas) panel->widget.wdata, XV_OWNER),
  71.         FRAME_LABEL, panel->cwd,
  72.         NULL);
  73. }
  74.  
  75. void xv_set_current_panel (WPanel *panel)
  76. {
  77.     if (panel != current_panel)
  78.         change_panel ();
  79. }
  80.  
  81. int x_panel_load_index (WPanel *panel, int idx)
  82. {
  83.     return 0;
  84. }
  85.  
  86. void xv_clear_area (Xv_window xv_win, Rect *rect)
  87. {
  88.     XClearArea (dpy, xv_get (xv_win, XV_XID),
  89.         rect->r_left, rect->r_top,
  90.         rect->r_width, rect->r_height,
  91.         FALSE);
  92. }
  93.  
  94. void xv_invalidate_rect (Canvas canvas, Rect *rect)
  95. {
  96.     Xv_window xv_win, xv_view;
  97.     Scrollbar scrollbar;
  98.     Rect rec;
  99.     int i, j;
  100.     Rectlist rl;
  101.     Rectnode rn;
  102.     
  103.     CANVAS_EACH_PAINT_WINDOW (canvas, xv_win)
  104.         if (rect == NULL) {
  105.             rec.r_left = 0;
  106.             rec.r_top = 0;
  107.             rec.r_width = xv_get (xv_win, XV_WIDTH);
  108.             rec.r_height = xv_get (xv_win, XV_HEIGHT);
  109.             xv_clear_area (xv_win, &rec);
  110.         } else
  111.             rec = *rect;
  112.         xv_view = xv_get (xv_win, CANVAS_PAINT_VIEW_WINDOW);
  113.         scrollbar = (Scrollbar) xv_get (canvas, OPENWIN_HORIZONTAL_SCROLLBAR, xv_win);
  114.         if (scrollbar != XV_NULL) {
  115.             i = xv_get (scrollbar, SCROLLBAR_VIEW_START);
  116.             j = xv_get (xv_view, XV_WIDTH);
  117.             if (rec.r_left < i)
  118.                 rec.r_left = i;
  119.             if (rec.r_left + rec.r_width > i + j)
  120.                 rec.r_width = i + j - rec.r_left;
  121.         }
  122.         scrollbar = (Scrollbar) xv_get (canvas, OPENWIN_VERTICAL_SCROLLBAR, xv_win);
  123.         if (scrollbar != XV_NULL) {
  124.             i = xv_get (scrollbar, SCROLLBAR_VIEW_START) * 
  125.                 xv_get (scrollbar, SCROLLBAR_PIXELS_PER_UNIT);
  126.             j = xv_get (xv_view, XV_HEIGHT);
  127.             if (rec.r_top < i)
  128.                 rec.r_top = i;
  129.             if (rec.r_top + rec.r_height > i + j)
  130.                 rec.r_height = i + j - rec.r_top;
  131.         }
  132.         rn.rn_next = NULL;
  133.         rn.rn_rect = rec;
  134.         rl.rl_x = 0;
  135.         rl.rl_y = 0;
  136.         rl.rl_head = rl.rl_tail = &rn;
  137.         rl.rl_bound = rec;
  138.         xv_panel_repaint_proc (canvas, xv_win, &rl);
  139.     CANVAS_END_EACH
  140. }
  141.  
  142. void xv_invalidate_item (Canvas canvas, int idx)
  143. {
  144.     Rect rect;
  145.     WPanel *panel = (WPanel *) xv_get (canvas, XV_KEY_DATA, KEY_DATA_PANEL);
  146.     
  147.     rect_construct (&rect, PANELBORDER, PANELBORDER + panel->item_height * idx,
  148.                            panel->total_width, panel->item_height);
  149.     xv_invalidate_rect (canvas, &rect);
  150. }
  151.  
  152. /* This procedure should be called whenever we change a f.marked file attribute
  153.    as a result of the program action, not by user clicking */
  154. void x_panel_select_item (WPanel *panel, int idx, int value)
  155. {
  156.     Canvas canvas = (Canvas) (panel->widget.wdata);
  157.  
  158.     xv_invalidate_item (canvas, idx);
  159. }
  160.  
  161. typedef enum {
  162.     MIP_UP, MIP_DOWN, MIP_PAGEUP, MIP_PAGEDOWN, MIP_HOME, MIP_END,
  163. } mipaction;
  164.  
  165. static void moveinpanel (Canvas canvas, Xv_window paint, mipaction action)
  166. {
  167.     WPanel *panel = (WPanel *) xv_get (canvas, XV_KEY_DATA, KEY_DATA_PANEL);
  168.     Scrollbar scroll = (Scrollbar) xv_get (canvas, OPENWIN_VERTICAL_SCROLLBAR,
  169.         xv_get (paint, CANVAS_PAINT_VIEW_WINDOW));
  170.     int newsel, newstart;
  171.     int start = xv_get (scroll, SCROLLBAR_VIEW_START);
  172.     int length = xv_get (scroll, SCROLLBAR_VIEW_LENGTH);
  173.     int lasttop = panel->count - length;
  174.     
  175.     newstart = start;
  176.     newsel = panel->selected;
  177.     switch (action) {
  178.         case MIP_PAGEUP:
  179.             if (newsel > start)
  180.                 newsel = start;
  181.             else {
  182.                 newstart -= length - 1;
  183.                 newsel -= length - 1;
  184.             }
  185.             break;
  186.         case MIP_PAGEDOWN:
  187.         if (newsel < start + length - 1)
  188.             newsel = start + length - 1;
  189.         else {
  190.             newstart += length - 1;
  191.             newsel += length - 1;
  192.         }
  193.         break;
  194.     case MIP_HOME:
  195.         newsel = 0;
  196.         newstart = 0;
  197.         break;
  198.     case MIP_END:
  199.         newsel = panel->count - 1;
  200.         newstart = lasttop;
  201.         break;
  202.     case MIP_UP:
  203.         if (newsel <= start)
  204.             newstart -= length / 2 - 1;
  205.         newsel--;
  206.         break;
  207.     case MIP_DOWN:
  208.         if (newsel >= start + length - 1) {
  209.             newstart += length / 2 - 1;
  210.         }
  211.         newsel++;
  212.         break;
  213.     }
  214.     if (newsel > panel->count - 1)
  215.         newsel = panel->count - 1;
  216.     if (newsel < 0)
  217.         newsel = 0;
  218.     if (newstart > lasttop)
  219.         newstart = lasttop;
  220.     if (newstart < 0)
  221.         newstart = 0;
  222.  
  223.     if (newstart != start || newsel != panel->selected) {    
  224.         if (newstart != start)
  225.             xv_set (scroll,
  226.                 SCROLLBAR_VIEW_START, newstart,
  227.                 NULL);
  228.             
  229.         if (newsel != panel->selected) {
  230.             unselect_item (panel);
  231.             panel->selected = newsel;
  232.             select_item (panel);
  233.         }
  234.  
  235.     }
  236. }
  237.  
  238. static WPanel *drag_panel;
  239. struct copy_move_in_panel {
  240.     int copy;
  241.     char *to;
  242.     WPanel *from;
  243. };
  244.  
  245. static copymove_in_panel (struct copy_move_in_panel *cmip)
  246. {
  247.     WPanel *panel = current_panel;
  248.     
  249.     xv_set_current_panel (cmip->from);
  250.     copymove_cmd_with_default (cmip->copy, cmip->to);
  251.     free (cmip->to);
  252.     free (cmip);
  253.     xv_set_current_panel (panel);
  254. }
  255.  
  256. static void delete_cmd_in_panel (WPanel *panel)
  257. {
  258.     xv_set_current_panel (panel);
  259.     delete_cmd ();
  260. }
  261.  
  262. struct user_drop {
  263.     WPanel *panel;
  264.     char *filename;
  265.     char *drops;
  266. };
  267.  
  268. static user_drop (struct user_drop *usdr)
  269. {
  270.     WPanel *panel = current_panel;
  271.     
  272.     xv_set_current_panel (usdr->panel);
  273.     regex_command (usdr->filename, "Drop", usdr->drops);
  274.     free (usdr->drops);
  275.     free (usdr);
  276.     xv_set_current_panel (panel);
  277. }
  278.  
  279. static int selection_convert (Selection_owner seln, Atom *type, Xv_opaque *data,
  280.     unsigned long *length, int *format)
  281. {
  282.     Xv_Server server = XV_SERVER_FROM_WINDOW (xv_get (seln, XV_OWNER));
  283.     
  284.     if (*type == (Atom) xv_get (server, SERVER_ATOM, "_SUN_SELECTION_END") ||
  285.         *type == (Atom) xv_get (server, SERVER_ATOM, "_SUN_DRAGDROP_DONE")) {
  286.         *format = 32;
  287.         *length = 0;
  288.         *data = XV_NULL;
  289.         *type = (Atom) xv_get (server, SERVER_ATOM, "NULL");
  290.         return TRUE;
  291.     } else if (*type == (Atom) xv_get (server, SERVER_ATOM, "DELETE")) {
  292.         xv_post_proc (midnight_dlg, (void (*)(void *))delete_cmd_in_panel,
  293.             (void *) drag_panel);
  294.         *format = 32;
  295.         *length = 0;
  296.         *data = XV_NULL;
  297.         *type = (Atom) xv_get (server, SERVER_ATOM, "NULL");
  298.         return TRUE;
  299.     } else
  300.         return sel_convert_proc (seln, type, data, length, format);
  301. }
  302.  
  303. static void start_drag (Xv_window paint, Event *event, Canvas canvas)
  304. {
  305.     Dnd dnd;
  306.     Selection_item sel_item;
  307.     WPanel *panel;
  308.     char *p, *q;
  309.     int i, copy = (event_shift_is_down (event) || event_ctrl_is_down (event));
  310.     int trailslash;
  311.     Xv_Server server = XV_SERVER_FROM_WINDOW (paint);
  312.     
  313.     drag_panel = panel = (WPanel *) xv_get (canvas, XV_KEY_DATA, KEY_DATA_PANEL);
  314.     dnd = xv_create (paint, DRAGDROP,
  315.         DND_TYPE, i ? DND_COPY : DND_MOVE,
  316.         SEL_CONVERT_PROC, selection_convert,
  317.         DND_ACCEPT_CURSOR, dropcursor,
  318.         NULL);
  319.     if (i) {
  320.         xv_set (dnd,
  321.             DND_CURSOR, xv_create (XV_NULL, CURSOR,
  322.                 CURSOR_SRC_CHAR, OLC_COPY_PTR,
  323.                 CURSOR_MASK_CHAR, OLC_COPY_MASK_PTR,
  324.                 NULL),
  325.             NULL);
  326.     } else
  327.         xv_set (dnd,
  328.             DND_CURSOR, xv_create (XV_NULL, CURSOR,
  329.                 CURSOR_SRC_CHAR, OLC_MOVE_PTR,
  330.                 CURSOR_MASK_CHAR, OLC_MOVE_MASK_PTR,
  331.                 NULL),
  332.         NULL);
  333.     p = "";
  334.     trailslash = (panel->cwd [strlen (panel->cwd) - 1] == '/');
  335.     for (i = 0; i < panel->count; i++)
  336.         if (panel->dir.list [i].f.marked) {
  337.             q = p;
  338.             if (trailslash)
  339.                 p = copy_strings (q, panel->cwd, panel->dir.list [i].fname, 
  340.                     " ", NULL);
  341.             else
  342.                 p = copy_strings (q, panel->cwd, "/", panel->dir.list [i].fname, 
  343.                     " ", NULL);
  344.             if (*q)
  345.                 free (q);
  346.         }
  347.     if (!*p) {
  348.         if (trailslash)
  349.             p = copy_strings (panel->cwd, 
  350.                 panel->dir.list [panel->selected].fname, NULL);
  351.         else
  352.             p = copy_strings (panel->cwd, "/", 
  353.                 panel->dir.list [panel->selected].fname, " ", NULL);
  354.     }
  355.     sel_item = xv_create (dnd, SELECTION_ITEM,
  356.         SEL_TYPE, (Atom) XA_STRING,
  357.         SEL_DATA, p,
  358.         NULL);
  359.     xv_create (dnd, SELECTION_ITEM,
  360.         SEL_TYPE, (Atom) xv_get (server, SERVER_ATOM, "_MXC_PANELID"),
  361.         SEL_FORMAT, sizeof (WPanel *) * 8,
  362.         SEL_LENGTH, 1,
  363.         SEL_DATA, &drag_panel,
  364.         NULL);
  365.     dnd_send_drop (dnd);
  366.     xv_destroy_safe (dnd);
  367. }
  368.  
  369. static void do_drop (Xv_window paint, Event *event, Canvas canvas, 
  370.     int in, int idx)
  371. {
  372.     Selection_requestor sel;
  373.     Xv_server server;
  374.     WPanel **ppanel;
  375.     WPanel *panel;
  376.     char *p;
  377.     int trailslash;
  378.     struct copy_move_in_panel *cmip;
  379.     struct user_drop *usdr;
  380.  
  381.     switch (event_action (event)) {
  382.     case ACTION_DRAG_PREVIEW:
  383.         return;
  384.     case ACTION_DRAG_COPY:
  385.     case ACTION_DRAG_MOVE:
  386.     case ACTION_DRAG_LOAD: 
  387.         server = XV_SERVER_FROM_WINDOW (paint);
  388.         sel = (Selection_requestor) 
  389.             xv_get (canvas, XV_KEY_DATA, KEY_DATA_SELREQ);
  390.         if (dnd_decode_drop (sel, event) != XV_ERROR) {
  391.             int length, format;
  392.             char *q;
  393.             
  394.             xv_set (sel, SEL_TYPE, XA_STRING, NULL);
  395.             q = (char *) xv_get (sel, SEL_DATA, &length, &format);
  396.             if (length != SEL_ERROR) {
  397.           panel = (WPanel *) xv_get (canvas, XV_KEY_DATA, KEY_DATA_PANEL);
  398.                 if (!in || S_ISDIR (panel->dir.list [idx].buf.st_mode)) {
  399.                     xv_set (sel, 
  400.                         SEL_TYPE, (Atom) xv_get (server, SERVER_ATOM, "_MXC_PANELID"),
  401.                         NULL);
  402.               ppanel = (WPanel **) xv_get (sel, SEL_DATA, &length, &format);
  403.               trailslash = (panel->cwd [strlen (panel->cwd) - 1] == '/');
  404.               if (length != SEL_ERROR) {
  405.                 if (!in) {
  406.                 p = strdup (panel->cwd);
  407.                 } else {
  408.                     if (trailslash)
  409.                         p = copy_strings (panel->cwd, 
  410.                                       panel->dir.list [idx].fname, NULL);
  411.                     else
  412.                         p = copy_strings (panel->cwd, "/",
  413.                                       panel->dir.list [idx].fname, NULL);
  414.                 }
  415.                 cmip = (struct copy_move_in_panel *)
  416.                     xmalloc (sizeof (struct copy_move_in_panel),
  417.                     "Copy/Move in Panel");
  418.                 cmip->copy = (event_action (event) == ACTION_COPY);
  419.                 cmip->from = *ppanel;
  420.                 cmip->to = p;
  421.                 xv_post_proc(midnight_dlg, 
  422.                              (void (*) (void *))copymove_in_panel,
  423.                              (void *) cmip);
  424.                 free ((char *) ppanel);              
  425.               }
  426.               free (q);
  427.           } else {
  428.             usdr = (struct user_drop *)
  429.                 xmalloc (sizeof (struct user_drop),
  430.                 "User drop");
  431.             usdr->panel = panel;
  432.             usdr->filename = panel->dir.list [idx].fname;
  433.             usdr->drops = q;
  434.               xv_post_proc(midnight_dlg,
  435.                        (void (*) (void *))user_drop,
  436.                        (void *) usdr);
  437.           }
  438.             }
  439.             xv_set (sel, SEL_TYPE_NAME, "_SUN_SELECTION_END", NULL);
  440.             xv_get (sel, SEL_DATA, &length, &format);
  441.             dnd_done (sel);
  442.         }
  443.     }
  444. }
  445.  
  446. static int xv_get_text_len (WPanel *panel, char *text)
  447. {
  448.     Font_string_dims dims;
  449.     
  450.     xv_get ((Font) (panel->font), FONT_STRING_DIMS, text, &dims);
  451.     return dims.width;
  452. }
  453.  
  454. static void xv_insert_panel_item (Canvas canvas, WPanel *panel, int idx)
  455. {
  456.     int top = panel->fmt_count;
  457.     int just_mode, i, len;
  458.     char *txt;
  459.     file_entry *fe = & panel->dir.list [idx];
  460.     int marked = fe->f.marked;
  461.     int isdir = S_ISDIR (panel->dir.list [idx].buf.st_mode);
  462.     static char buffer [1024];
  463.     char *p = buffer;
  464.     
  465.     for (i = 0; i < top; i++) {
  466.         just_mode = panel->format [i].just_mode;
  467.         if (panel->format [i].string_fn) {
  468.             txt = (*panel->format [i].string_fn) (fe, 0);
  469.         } else
  470.             txt = " ";
  471.         if (panel->format [i].string_fn == string_file_type) {
  472.         panel->format [i].field_len = 18;
  473.         p [0] = 3 + ((*txt == '/') ? 1 : 0);
  474.         p [1] = 0;
  475.         p += 2;
  476.         } else {
  477.         len = xv_get_text_len (panel, txt) + 2;
  478.         if (panel->format [i].field_len < len)
  479.             panel->format [i].field_len = len;
  480.         p [0] = just_mode + 1;
  481.         strcpy (p + 1, txt);
  482.         p = index (p + 1, 0) + 1;
  483.     }                
  484.     }
  485.     *(p++) = 0;
  486.     fe->cache = xmalloc (p - buffer, "xview display cache");
  487.     bcopy (buffer, fe->cache, p - buffer);
  488. }
  489.  
  490. void x_select_item (WPanel *panel)
  491. {
  492.     Canvas canvas = (Canvas) panel->widget.wdata;
  493.     int idx = panel->selected;
  494.  
  495.     xv_invalidate_item (canvas, idx);
  496. }
  497.  
  498. void x_unselect_item (WPanel *panel)
  499. {
  500.     Canvas canvas = (Canvas) panel->widget.wdata;
  501.     int idx = panel->selected;
  502.  
  503.     panel->selected = -1;
  504.     xv_invalidate_item (canvas, idx);
  505.     panel->selected = idx;
  506. }
  507.  
  508. void x_fill_panel (WPanel *panel)
  509. {
  510.     int i;
  511.     int w, h;
  512.     Xv_Window win, paint;
  513.     Canvas canvas = (Canvas) panel->widget.wdata;
  514.     Scrollbar scrollbar;
  515.     Rect rect;
  516.  
  517.     for (i = 0; i < panel->fmt_count; i++)
  518.         panel->format [i].field_len = 2;
  519.         
  520.     for (i = 0; i < panel->count; i++)
  521.         xv_insert_panel_item (canvas, panel, i);
  522.         
  523.     for (i = 0, panel->total_width = 2 * PANELITEMBORDER; 
  524.          i < panel->fmt_count; i++)
  525.         panel->total_width += panel->format [i].field_len;
  526.         
  527.     w = panel->total_width + 2 * PANELBORDER;
  528.     h = panel->item_height * panel->count + 2 * PANELBORDER;
  529.     
  530.     xv_set (canvas,
  531.         CANVAS_MIN_PAINT_WIDTH, w,
  532.         CANVAS_MIN_PAINT_HEIGHT, h,
  533.         NULL);
  534.         
  535.     i = panel->item_height;
  536.     
  537.     rect.r_left = PANELBORDER;
  538.     rect.r_width = panel->total_width;
  539.     rect.r_top = PANELBORDER;
  540.     rect.r_height = h - 2 * PANELBORDER;
  541.     
  542.     OPENWIN_EACH_VIEW (canvas, win)
  543.         scrollbar = (Scrollbar) xv_get (canvas, OPENWIN_HORIZONTAL_SCROLLBAR, win);
  544.         if (scrollbar != XV_NULL)
  545.             xv_set (scrollbar,
  546.                 SCROLLBAR_OBJECT_LENGTH, w,
  547.                 NULL);
  548.         scrollbar = (Scrollbar) xv_get (canvas, OPENWIN_VERTICAL_SCROLLBAR, win);
  549.         if (scrollbar != XV_NULL)
  550.             xv_set (scrollbar,
  551.                 SCROLLBAR_PIXELS_PER_UNIT, i,
  552.                 SCROLLBAR_OBJECT_LENGTH, panel->count + 1,
  553.                 NULL);
  554.         paint = (Xv_window) xv_get (win, CANVAS_VIEW_PAINT_WINDOW);
  555.         xv_set (xv_get (paint, XV_KEY_DATA, KEY_DATA_TILE),
  556.             DROP_SITE_DELETE_REGION, NULL,
  557.             DROP_SITE_REGION, &rect,
  558.             NULL);
  559.     OPENWIN_END_EACH
  560.  
  561.     xv_invalidate_rect (canvas, NULL);
  562.     
  563. }
  564.  
  565. static void xv_panel_repaint_item (WPanel *panel, int idx, Xv_Window paint_window)
  566. {
  567.     int selmark = 0;
  568.     file_entry *fe = & panel->dir.list [idx];
  569.     Drawable xid = (Drawable) xv_get (paint_window, XV_XID);
  570.     unsigned long fg, bg, *xc;
  571.     GC gc = (GC) (panel->gc);
  572.     Rect rect;
  573.     char *cache = fe->cache;
  574.     XPoint xp [3];
  575.     char *p;
  576.     int i, w, x, h, y;
  577.     Server_image image, mask;
  578.     
  579.     if (cache == NULL)
  580.         return;
  581.     if (fe->f.marked)
  582.         selmark |= 1;
  583.     if (idx == panel->selected)
  584.         selmark |= 2;
  585.     
  586.     xc = (unsigned long *) xv_get (mccms, CMS_INDEX_TABLE);
  587.     
  588.     fg = xc [selmark * 2 + CMS_CONTROL_COLORS];
  589.     bg = xc [(selmark & 2) ? 1 : 0];
  590.     
  591.     rect_construct (&rect, PANELBORDER, PANELBORDER + idx * panel->item_height,
  592.                            panel->total_width, panel->item_height);
  593.     
  594.     XSetForeground (dpy, gc, bg);
  595.     XFillRectangle (dpy, xid, gc,
  596.         rect.r_left,
  597.         rect.r_top,
  598.         rect.r_width,
  599.         rect.r_height);
  600.  
  601.     if (selmark & 2) {
  602.         xp [0].x = rect.r_left;
  603.         xp [0].y = rect.r_top + rect.r_height;
  604.         xp [1].x = rect.r_left;
  605.         xp [1].y = rect.r_top;
  606.         xp [2].x = rect.r_left + rect.r_width - 1;
  607.         xp [2].y = rect.r_top;
  608.         XSetForeground (dpy, gc, xc [2]);
  609.         XDrawLines (dpy, xid, gc, xp, 3, CoordModeOrigin);
  610.         xp [0].x = rect.r_left + 1;
  611.         xp [0].y = rect.r_top + rect.r_height - 1;
  612.         xp [1].x = rect.r_left + rect.r_width - 1;
  613.         xp [1].y = rect.r_top + rect.r_height - 1;
  614.         xp [2].x = rect.r_left + rect.r_width - 1;
  615.         xp [2].y = rect.r_top;
  616.         XSetForeground (dpy, gc, xc [3]);
  617.         XDrawLines (dpy, xid, gc, xp, 3, CoordModeOrigin);
  618.     }
  619.     
  620.     XSetForeground (dpy, gc, fg);
  621.     XSetBackground (dpy, gc, bg);
  622.     rect.r_left += PANELITEMBORDER;
  623.     
  624.     for (i = 0, p = fe->cache; *p; p = strchr (p, 0) + 1, i++) {
  625.         if (*p <= 2) { /* i.e. either left or right justified text */
  626.             w = xv_get_text_len (panel, p + 1);
  627.             h = panel->ascent + panel->descent;
  628.             y = rect.r_top + panel->ascent + (panel->item_height - h) / 2;
  629.             if (*p == J_LEFT + 1)
  630.                 x = rect.r_left + 1;
  631.             else
  632.                 x = rect.r_left + panel->format [i].field_len - w - 1;
  633.             XDrawString (dpy, xid, gc, x, y, p + 1, strlen (p + 1));
  634.         } else {
  635.             switch (*p) {
  636.                 case 3: image = iconRegular [0]; mask = iconRegular [1]; break;
  637.                 case 4: image = iconDirectory [0]; mask = iconDirectory [1]; break;
  638.             }
  639.             XSetClipMask (dpy, gc, (Drawable) xv_get (mask, SERVER_IMAGE_PIXMAP));
  640.             x = rect.r_left + 2;
  641.             y = rect.r_top + (panel->item_height - 16) / 2;
  642.             XSetClipOrigin (dpy, gc, x, y);
  643.             XCopyArea (dpy, (Drawable) xv_get (image, SERVER_IMAGE_PIXMAP),
  644.                        xid, gc,
  645.                        0, 0, 
  646.                        16, 16, 
  647.                        x, y);
  648.             XSetClipMask (dpy, gc, None);
  649.         }
  650.         rect.r_left += panel->format [i].field_len;
  651.     }
  652. }
  653.  
  654. static void xv_panel_repaint_proc (Canvas canvas, Xv_Window paint_window,
  655.     Rectlist *repaint)
  656. {
  657.     int first, last;
  658.     WPanel *panel;
  659.     int i;
  660.     Rect rect;
  661.  
  662.     panel = (WPanel *) xv_get (canvas, XV_KEY_DATA, KEY_DATA_PANEL);
  663.         
  664. /* This stuff has to change as soon as we start supporting big icons display */
  665.     first = (repaint->rl_y + repaint->rl_bound.r_top - PANELBORDER) / panel->item_height;
  666.     last = (repaint->rl_y + repaint->rl_bound.r_top + repaint->rl_bound.r_height
  667.         - PANELBORDER - 1) / panel->item_height;
  668.     if (first < 0) {
  669.         first = 0;
  670.     }
  671.     if (last >= panel->count) {
  672.         last = panel->count - 1;
  673.     }
  674.     
  675.     /* First we clear all the areas around... */
  676.  
  677.     if (repaint->rl_x + repaint->rl_bound.r_left < PANELBORDER) {
  678.         rect.r_left = repaint->rl_x + repaint->rl_bound.r_left;
  679.         rect.r_width = PANELBORDER - rect.r_left;
  680.         rect.r_top = repaint->rl_y + repaint->rl_bound.r_top;
  681.         rect.r_height = repaint->rl_bound.r_height;
  682.         xv_clear_area (paint_window, &rect);
  683.     }
  684.  
  685.     if (repaint->rl_x + repaint->rl_bound.r_left + repaint->rl_bound.r_width
  686.         > PANELBORDER + panel->total_width) {
  687.         rect.r_left = PANELBORDER + panel->total_width;
  688.         rect.r_width = repaint->rl_x + repaint->rl_bound.r_left +
  689.             repaint->rl_bound.r_width - rect.r_left;
  690.         rect.r_top = repaint->rl_y + repaint->rl_bound.r_top;
  691.         rect.r_height = repaint->rl_bound.r_height;
  692.         xv_clear_area (paint_window, &rect);
  693.     }
  694.     
  695.     if (repaint->rl_y + repaint->rl_bound.r_top < PANELBORDER) {
  696.         rect.r_left = repaint->rl_x + repaint->rl_bound.r_left;
  697.         rect.r_width = rect.r_left + repaint->rl_bound.r_width;
  698.         if (rect.r_left < PANELBORDER)
  699.             rect.r_left = PANELBORDER;
  700.         if (rect.r_width > panel->total_width + PANELBORDER)
  701.             rect.r_width = panel->total_width + PANELBORDER - rect.r_left;
  702.         else
  703.             rect.r_width -= rect.r_left;
  704.         rect.r_top = repaint->rl_y + repaint->rl_bound.r_top;
  705.         rect.r_height = PANELBORDER - rect.r_top;
  706.         xv_clear_area (paint_window, &rect);
  707.     }
  708.  
  709.     if (repaint->rl_y + repaint->rl_bound.r_top + repaint->rl_bound.r_height
  710.         > PANELBORDER + panel->count * panel->item_height) {
  711.         rect.r_left = repaint->rl_x + repaint->rl_bound.r_left;
  712.         rect.r_width = rect.r_left + repaint->rl_bound.r_width;
  713.         if (rect.r_left < PANELBORDER)
  714.             rect.r_left = PANELBORDER;
  715.         if (rect.r_width > panel->total_width + PANELBORDER)
  716.             rect.r_width = panel->total_width + PANELBORDER - rect.r_left;
  717.         else
  718.             rect.r_width -= rect.r_left;
  719.         rect.r_top = PANELBORDER + panel->count * panel->item_height;
  720.         rect.r_height = repaint->rl_y + repaint->rl_bound.r_top + 
  721.             repaint->rl_bound.r_height - rect.r_top;
  722.         xv_clear_area (paint_window, &rect);
  723.     }
  724.  
  725.     for (i = first; i <= last; i++) {
  726.     xv_panel_repaint_item (panel, i, paint_window);
  727.     }
  728. }
  729.  
  730. static struct {
  731.     Canvas canvas;
  732.     int idx;
  733.     int btn_down_x, btn_down_y;
  734.     struct timeval prev_time;
  735. } click_info = { XV_NULL, -1, 0, 0, {0, 0}};
  736. static int xv_panel_grab = 0;
  737. static int wait_for_btnup = 0;
  738. static int rubber_adjust = 0;
  739. static int lastx, lasty, startx, starty;
  740. static GC xor_gc; 
  741.  
  742. /* Should select / invert selection of all the idx's inside 
  743.  * lastx, startx, lasty, starty 
  744.  * As a used side effect, setting lastx = startx = -1 should unmark all files
  745.  */
  746. static void xv_rubberband_select (WPanel *panel)
  747. {
  748.     int x1, y1, x2, y2, first, last, i;
  749.  
  750.     x1 = (startx < lastx) ? startx : lastx;
  751.     y1 = (starty < lasty) ? starty : lasty;
  752.     x2 = (startx > lastx) ? startx : lastx;
  753.     y2 = (starty > lasty) ? starty : lasty;
  754.  
  755.     /* This has to change because of big icons */    
  756.     if (x2 <= PANELBORDER || x1 >= panel->total_width + PANELBORDER) {
  757.         first = last = -1;
  758.     } else {
  759.         first = (y1 - PANELBORDER) / panel->item_height;
  760.         last = (y2 - PANELBORDER) / panel->item_height;
  761.     }
  762.     for (i = 0; i < panel->count; i++) {
  763.         if (i >= first && i <= last) {
  764.             if (rubber_adjust)
  765.                 do_file_mark (panel, i, panel->dir.list [i].f.marked ? 0 : 1);
  766.             else if (!panel->dir.list [i].f.marked)
  767.                 do_file_mark (panel, i, 1);
  768.         } else if (!rubber_adjust) {
  769.             if (panel->dir.list [i].f.marked)
  770.                 do_file_mark (panel, i, 0);
  771.         }
  772.     }
  773. }
  774.  
  775. int is_dbl_click (struct timeval *then, struct timeval *now)
  776. {
  777.     struct timeval delta;
  778.     static int multiclicktimeout = 0;
  779.     
  780.     delta.tv_sec = now->tv_sec - then->tv_sec;
  781.     if ((delta.tv_usec = now->tv_usec - then->tv_usec) < 0) {
  782.         delta.tv_usec += 1000000;
  783.         delta.tv_sec--;
  784.     }
  785.     if (multiclicktimeout == 0) {
  786.         multiclicktimeout == defaults_get_integer ("mxc.doubleclicktime",
  787.                                "Mxc.DoubleClickTime", 5);
  788.         if (multiclicktimeout < 2 || multiclicktimeout > 100)
  789.             multiclicktimeout = 5;
  790.     }   
  791.     if ((delta.tv_sec * 10 + delta.tv_usec / 100000) <= multiclicktimeout)
  792.         return 1;
  793.     return 0;
  794. }
  795.  
  796. static void draw_rubberband (Canvas canvas)
  797. {
  798.     Xv_window xv_win;
  799.     int x1, y1, x2, y2, width, height;
  800.     
  801.     x1 = (startx < lastx) ? startx : lastx;
  802.     y1 = (starty < lasty) ? starty : lasty;
  803.     x2 = (startx > lastx) ? startx : lastx;
  804.     y2 = (starty > lasty) ? starty : lasty;
  805.     width = x2 - x1;
  806.     height = y2 - y1;
  807.     
  808.     if (!width || !height)
  809.         return;
  810.     
  811.     CANVAS_EACH_PAINT_WINDOW (canvas, xv_win)
  812.          XDrawRectangle (dpy, xv_get (xv_win, XV_XID), xor_gc, x1, y1, 
  813.              width, height);
  814.     CANVAS_END_EACH
  815. }
  816.  
  817. static void xv_dblclick_proc (WPanel *panel, int idx)
  818. {
  819.     xv_set_current_panel (panel);    
  820.     if (panel->selected != idx)
  821.         panel->selected = idx; /* Should not happen :) */
  822.     xv_post_proc (midnight_dlg, (void (*)(void *))do_enter, (void *)panel);
  823. }
  824.  
  825. static WPanel *xv_filedepmenu_panel = NULL;
  826. static int xv_filedepmenu_idx;
  827. static char *xv_filedepmenu_free = NULL;
  828.  
  829. static void xv_filedepmenu_cmd (char *todo)
  830. {
  831.     char *p;
  832.     
  833.     p = strchr (todo, ' ');
  834.     *p = 0;
  835.     regex_command (p + 1, todo, NULL);
  836.     free (todo);
  837. }
  838.  
  839. static void xv_filedepmenu (Menu menu, Menu_item item)
  840. {
  841.     char *q;
  842.     char *p = (char *) xv_get (item, MENU_STRING);
  843.     
  844.     if (!strcmp (p, "Copy"))
  845.         xv_post_proc (midnight_dlg, (void (*)(void *))copy_cmd, (void *)NULL);
  846.     else if (!strcmp (p, "Move"))
  847.         xv_post_proc (midnight_dlg, (void (*)(void *))ren_cmd, (void *)NULL);
  848.     else if (!strcmp (p, "Delete"))
  849.         xv_post_proc (midnight_dlg, (void (*)(void *))delete_cmd, (void *)NULL);
  850.     else {
  851.         q = copy_strings (p, " ", xv_filedepmenu_panel->dir.list [xv_filedepmenu_idx].fname, NULL);
  852.         xv_post_proc (midnight_dlg, (void (*)(void *))xv_filedepmenu_cmd, (void *)q);
  853.     }
  854.     if (xv_filedepmenu_free)
  855.         free (xv_filedepmenu_free);
  856. }
  857.  
  858. static void xv_mouse_event (Canvas canvas, Xv_window paint, Event *event)
  859. {
  860.     WPanel *panel = (WPanel *) xv_get (canvas, XV_KEY_DATA, KEY_DATA_PANEL);
  861.     int in, idx;
  862.     
  863.     if (event_x (event) < PANELBORDER || 
  864.         event_x (event) >= PANELBORDER + panel->total_width ||
  865.         event_y (event) < PANELBORDER || 
  866.         event_y (event) >= PANELBORDER + panel->count * panel->item_height) {
  867.         in = 0;
  868.     } else {
  869.         in = 1;
  870.         idx = (event_y (event) - PANELBORDER) / panel->item_height;
  871.     }
  872.     switch (event_action (event)) {
  873.         case ACTION_DRAG_PREVIEW:
  874.         case ACTION_DRAG_COPY:
  875.         case ACTION_DRAG_MOVE:
  876.         case ACTION_DRAG_LOAD:
  877.             do_drop (paint, event, canvas, in, idx);
  878.             return;
  879.     }
  880.     if (xv_panel_grab) {
  881.         if (wait_for_btnup) {
  882.             if (event_action (event) == LOC_DRAG) {
  883.                 static int threshold;
  884.                 static int dist_x, dist_y;
  885.                 
  886.                 if (threshold == 0)
  887.                     threshold = defaults_get_integer (
  888.                         "mxc.clickmovethreshold",
  889.                         "Mxc.ClickMoveThreshold", 10);
  890.                         
  891.                 dist_x = event_x (event) - click_info.btn_down_x;
  892.                 if (dist_x < 0)
  893.                     dist_x = - dist_x;
  894.                 dist_y = event_y (event) - click_info.btn_down_y;
  895.                 if (dist_y < 0)
  896.                     dist_y = - dist_y;
  897.                 if (dist_x > threshold || dist_y > threshold ||
  898.                     event_ctrl_is_down (event) || event_shift_is_down (event)) {
  899.                     xv_panel_grab = 0;
  900.                     wait_for_btnup = 0;
  901.                     start_drag (paint, event, canvas);
  902.                 }
  903.                 return;        
  904.             }
  905.             if (event_is_button (event) && event_is_down (event)) {
  906.                 return;
  907.             }
  908.             if (event_action (event) == ACTION_SELECT) {
  909.                 if (is_dbl_click (&click_info.prev_time, &event_time (event))) {
  910.                     /* Should we handle tripple clicks? 
  911.                      * Maybe for selecting/unselecting all the files :) */
  912.                     click_info.prev_time.tv_sec = 0;
  913.                     click_info.prev_time.tv_usec = 0;
  914.                     xv_dblclick_proc (panel, click_info.idx);
  915.                 } else {
  916.                     click_info.prev_time = event_time (event);
  917.                 }
  918.                 xv_panel_grab = 0;
  919.                 return;
  920.             }
  921.             if (event_action (event) == ACTION_ADJUST) {
  922.                 xv_panel_grab = 0;
  923.                 return;
  924.             }
  925.             if (!event_is_button (event) && !event_is_iso (event))
  926.                 return;
  927.             xv_panel_grab = 0;
  928.             return;
  929.         } else {
  930.             if (event_action (event) == LOC_DRAG) {
  931.                 draw_rubberband (canvas);
  932.                 lastx = event_x (event);
  933.                 lasty = event_y (event);
  934.                 draw_rubberband (canvas);
  935.                 return;
  936.             }
  937.             if (event_is_button (event)) {
  938.                 if (event_is_down (event)) {
  939.                     draw_rubberband (canvas);
  940.                     XFreeGC (dpy, xor_gc);
  941.                     xv_panel_grab = 0;
  942.                     return;
  943.                 }
  944.             } else {
  945.                 if (event_is_iso (event)) {
  946.                     draw_rubberband (canvas);
  947.                     XFreeGC (dpy, xor_gc);
  948.                     xv_panel_grab = 0;
  949.                 }
  950.                 return;
  951.             }
  952.             draw_rubberband (canvas);
  953.             xv_panel_grab = 0;
  954.             XFreeGC (dpy, xor_gc);
  955.             xv_rubberband_select (panel);
  956.             return;
  957.         } 
  958.     }
  959.     switch (event_action (event)) {
  960.         case ACTION_HELP:
  961.             if (event_is_down (event)) {
  962.             }
  963.             return;
  964.         case ACTION_MENU:
  965.             if (event_is_down (event)) {
  966.                 static Menu menu = XV_NULL;
  967.                 char *p, *q, c;
  968.                 
  969.                 if (menu != XV_NULL)
  970.                     xv_destroy (menu);
  971.                 menu = (Menu) xv_create (XV_NULL, MENU,
  972.                     MENU_NOTIFY_PROC, xv_filedepmenu,
  973.                     MENU_TITLE_ITEM, panel->dir.list [idx].fname,
  974.                     MENU_STRINGS, "Open", "View", "Edit", "Copy", "Move", "Delete", NULL,
  975.                     NULL);
  976.                 p = regex_command (panel->dir.list [idx].fname, NULL, NULL);
  977.                 if (p != NULL) {
  978.                     for (;;) {
  979.                         while (*p == ' ' || *p == '\t')
  980.                             p++;
  981.                         if (!*p)
  982.                             break;
  983.                         q = p;
  984.                         while (*q && *q != ' ' && *q != '\t')
  985.                             q++;
  986.                         c = *q;
  987.                         *q = 0;
  988.                         xv_set (menu,
  989.                             MENU_ITEM,
  990.                                 MENU_STRING, p,
  991.                                 NULL,
  992.                             NULL);
  993.                         if (!c)
  994.                             break;
  995.                         p = q + 1;
  996.                     }
  997.                 }
  998.                 xv_filedepmenu_panel = panel;
  999.                 xv_filedepmenu_idx = idx;
  1000.                 xv_filedepmenu_free = p;
  1001.                 menu_show (menu, paint, event, NULL);
  1002.             }
  1003.             return;
  1004.         case ACTION_SELECT:
  1005.         case ACTION_ADJUST:
  1006.             if (event_is_down (event)) {
  1007.                 if (in) {
  1008.                     if (click_info.idx != idx) {
  1009.                         click_info.idx = idx;
  1010.                         click_info.prev_time.tv_sec = 0;
  1011.                         click_info.prev_time.tv_usec = 0;
  1012.                     }
  1013.                     click_info.btn_down_x = event_x (event);
  1014.                     click_info.btn_down_y = event_y (event);
  1015.                     if (event_action (event) == ACTION_SELECT) {
  1016.                         if (panel->selected != idx) {
  1017.                             unselect_item (panel);
  1018.                             panel->selected = idx;
  1019.                             select_item (panel);
  1020.                         }
  1021.                     } else {
  1022.                         do_file_mark (panel, idx, 
  1023.                             panel->dir.list [idx].f.marked ? 0 : 1);
  1024.                     }
  1025.                     wait_for_btnup = 1;
  1026.                     xv_panel_grab = 1;
  1027.                 } else {
  1028.                     if (event_action (event) == ACTION_SELECT) {
  1029.                         rubber_adjust = 0;
  1030.                         lastx = -1;
  1031.                         startx = -1;
  1032.                         xv_rubberband_select (panel);
  1033.                     } else
  1034.                         rubber_adjust = 1;
  1035.                     xor_gc = XCreateGC (dpy, xv_get (paint, XV_XID), 0, 0);
  1036.                     XSetForeground (dpy, xor_gc, xv_get (canvas, WIN_FOREGROUND_COLOR));
  1037.                     XSetFunction (dpy, xor_gc, GXxor);
  1038.                     XSetLineAttributes (dpy, xor_gc, 1, LineSolid, CapNotLast, JoinRound);
  1039.                     lastx = startx = event_x (event);
  1040.                     lasty = starty = event_y (event);
  1041.                     wait_for_btnup = 0;
  1042.                     xv_panel_grab = 1;
  1043.                 }
  1044.             }
  1045.     }
  1046. }
  1047.  
  1048. static int xv_panel_event_proc (Xv_window paint, Event *event)
  1049. {
  1050.     Canvas canvas = (Canvas) xv_get (paint, CANVAS_PAINT_CANVAS_WINDOW);
  1051.     WPanel *panel;
  1052.     
  1053.     panel = (WPanel *) xv_get (canvas, XV_KEY_DATA, KEY_DATA_PANEL);
  1054.     
  1055.     if (event_is_down (event) && event_is_button (event))
  1056.         xv_set_current_panel (panel);
  1057.     
  1058.     switch (event_action (event)) {
  1059.         case ACTION_SELECT:
  1060.         case ACTION_ADJUST:
  1061.         case LOC_DRAG:
  1062.         case ACTION_MENU:
  1063.         case ACTION_HELP:
  1064.         case ACTION_DRAG_PREVIEW:
  1065.         case ACTION_DRAG_COPY:
  1066.         case ACTION_DRAG_MOVE:
  1067.         case ACTION_DRAG_LOAD:
  1068.             xv_mouse_event (canvas, paint, event);
  1069.             return 0;
  1070.     }
  1071.     
  1072.     if (event_is_up (event))
  1073.         return 0;
  1074.     
  1075.     switch (event_action (event)) {
  1076.         case KBD_USE:
  1077.             xv_set_current_panel (panel);
  1078.             break;
  1079.         case ACTION_GO_COLUMN_FORWARD:
  1080.             moveinpanel (canvas, paint, MIP_DOWN);
  1081.             break;
  1082.         case ACTION_GO_COLUMN_BACKWARD:
  1083.             moveinpanel (canvas, paint, MIP_UP);
  1084.             break;
  1085.         case ACTION_GO_DOCUMENT_START:
  1086.             moveinpanel (canvas, paint, MIP_HOME);
  1087.             break;
  1088.         case ACTION_GO_DOCUMENT_END:
  1089.             moveinpanel (canvas, paint, MIP_END);
  1090.             break;
  1091.         case ACTION_GO_PAGE_BACKWARD:
  1092.             moveinpanel (canvas, paint, MIP_PAGEUP);
  1093.             break;
  1094.         case ACTION_GO_PAGE_FORWARD:
  1095.             moveinpanel (canvas, paint, MIP_PAGEDOWN);
  1096.             break;
  1097.         default:
  1098.             if (event_id (event) == '\n' || event_id (event) == '\r') {
  1099.                 xv_post_proc (midnight_dlg, 
  1100.                     (void (*)(void *))do_enter, (void *) panel);
  1101.             } else if (event_id (event) == '\t') {
  1102.                 if (((Widget *)cmdline)->wdata != (widget_data) NULL)
  1103.                     xv_set (((Widget *)cmdline)->wdata,
  1104.                         WIN_SET_FOCUS,
  1105.                         NULL);
  1106.             } else if (event_is_key_left (event) || event_is_key_right (event) ||
  1107.             event_is_key_top (event) || event_is_key_bottom (event)) {
  1108.             int i = 1;
  1109.         
  1110.             if (event_is_key_left (event))
  1111.                     i = event_id (event) - KEY_LEFTFIRST + 1;
  1112.             else if (event_is_key_right (event))
  1113.                     i = event_id (event) - KEY_RIGHTFIRST + 1;
  1114.             else if (event_is_key_top (event))
  1115.                     i = event_id (event) - KEY_TOPFIRST + 1;
  1116.             else if (event_is_key_bottom (event))
  1117.                     i = event_id (event) - KEY_BOTTOMFIRST + 1;
  1118.         {
  1119.             int j;
  1120.             WButtonBar *bb = 
  1121.                 find_buttonbar (midnight_dlg, (Widget *) panel);
  1122.             
  1123.             if (bb != (WButtonBar *) NULL) {
  1124.                 if (strcmp (bb->labels [i - 1].text, "PullDn")) {
  1125.                     if (bb->labels [i - 1].function)
  1126.                         xv_post_proc (midnight_dlg,
  1127.                             *bb->labels [i - 1].function,
  1128.                             bb->labels [i - 1].data);
  1129.                 }
  1130.             }
  1131.         }                
  1132.             }
  1133.     }
  1134.     
  1135.     return 0;
  1136. }
  1137.  
  1138. char *xv_create_canvas_gc (Canvas canvas)
  1139. {
  1140.     GC gc = XCreateGC (dpy, 
  1141.         (Drawable) xv_get (xv_get (canvas, CANVAS_NTH_PAINT_WINDOW, 0), XV_XID),
  1142.         0, 0);
  1143.     
  1144.     XSetFont (dpy, gc, xv_get (xv_get (canvas, XV_FONT), XV_XID));
  1145.     XSetLineAttributes (dpy, gc, 1, LineSolid, JoinRound, CapNotLast);
  1146.     XSetGraphicsExposures (dpy, gc, False);
  1147.     
  1148.     return (char *) gc;
  1149. }
  1150.  
  1151. void xv_panel_split_proc (Xv_Window origview, Xv_Window newview, int pos)
  1152. {
  1153.     Rect *rect = (Rect *) xv_get (
  1154.         xv_get (origview, XV_KEY_DATA, KEY_DATA_TILE), DROP_SITE_REGION);
  1155.  
  1156.     xv_set (newview, 
  1157.         XV_KEY_DATA, KEY_DATA_TILE, xv_create (newview, DROP_SITE_ITEM, 
  1158.             DROP_SITE_EVENT_MASK, DND_ENTERLEAVE,
  1159.             DROP_SITE_REGION, rect,
  1160.             NULL),
  1161.         NULL);
  1162.         
  1163.     free (rect);
  1164. }
  1165.         
  1166. int x_create_panel (Dlg_head *h, widget_data parent, WPanel *panel)
  1167. {
  1168.     Canvas canvas = 
  1169.         (Canvas) x_get_parent_object ((Widget *) panel, parent);
  1170.     Xv_opaque dropsite_item;
  1171.     Xv_window win;
  1172.     Rect rect;
  1173.  
  1174.     rect.r_left = PANELBORDER;
  1175.     rect.r_width = 220;
  1176.     rect.r_top = PANELBORDER;
  1177.     rect.r_height = 220;
  1178.     xv_set (canvas, 
  1179.         XV_KEY_DATA, KEY_DATA_PANEL, panel,
  1180.         XV_KEY_DATA, KEY_DATA_PANEL_CONTAINER, xv_get (canvas, XV_OWNER),
  1181.         CANVAS_PAINTWINDOW_ATTRS,
  1182.             WIN_CONSUME_EVENTS,
  1183.                 KBD_DONE, KBD_USE, WIN_ASCII_EVENTS, WIN_LEFT_KEYS, WIN_TOP_KEYS,
  1184.                 WIN_RIGHT_KEYS, WIN_META_EVENTS, WIN_EDIT_KEYS, WIN_MOTION_KEYS,
  1185.                 WIN_TEXT_KEYS, 
  1186.                 WIN_UP_EVENTS, WIN_MOUSE_BUTTONS, LOC_DRAG,
  1187.                 ACTION_HELP, ACTION_DRAG_PREVIEW, ACTION_DRAG_LOAD, ACTION_DRAG_COPY,
  1188.                 ACTION_DRAG_MOVE,
  1189.                 NULL,
  1190.             WIN_EVENT_PROC, xv_panel_event_proc,
  1191.             NULL,
  1192.         CANVAS_X_PAINT_WINDOW, FALSE,
  1193.         CANVAS_RETAINED, FALSE,
  1194.         CANVAS_REPAINT_PROC, xv_panel_repaint_proc,
  1195.         WIN_CMS, mccms,
  1196.         OPENWIN_SPLIT,
  1197.             OPENWIN_SPLIT_INIT_PROC, xv_panel_split_proc,
  1198.             NULL,
  1199.         NULL);
  1200.         
  1201.     CANVAS_EACH_PAINT_WINDOW (canvas, win)
  1202.         xv_set (win,
  1203.             XV_KEY_DATA, KEY_DATA_TILE, xv_create (win, DROP_SITE_ITEM, 
  1204.                 DROP_SITE_EVENT_MASK, DND_ENTERLEAVE,
  1205.                 DROP_SITE_REGION, &rect,
  1206.                 NULL),
  1207.             NULL);
  1208.     CANVAS_END_EACH
  1209.     
  1210.     panel->widget.wdata = (widget_data) canvas;
  1211.     panel->gc = xv_create_canvas_gc (canvas);
  1212.     panel->font = (void *) xv_get (canvas, XV_FONT);
  1213.     panel->ascent = ((XFontStruct *) xv_get (
  1214.         xv_get (canvas, XV_FONT), FONT_INFO))->ascent;
  1215.     panel->descent = ((XFontStruct *) xv_get (
  1216.         xv_get (canvas, XV_FONT), FONT_INFO))->descent;
  1217.     panel->item_height = panel->ascent + panel->descent;
  1218.     if (panel->item_height < 16)
  1219.         panel->item_height = 16;
  1220.     panel->item_height += 2 * PANELITEMBORDER;
  1221.     x_fill_panel (panel);
  1222.     return 1;
  1223. }
  1224.  
  1225. void x_panel_set_size (int idx)
  1226. {
  1227. }
  1228.  
  1229. void set_attr (int h, int m)
  1230. {
  1231. }
  1232.